package org.osgroup.monitor;

import org.osgroup.project.BaseProject;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 项目心跳监控守护进程
 * 
 * <p>负责监控所有注册项目的心跳状态</p>
 * <p>主要功能：</p>
 * <ul>
 *   <li>定期检查项目心跳</li>
 *   <li>检测心跳超时</li>
 *   <li>触发异常告警</li>
 *   <li>生成监控报告</li>
 * </ul>
 * 
 * @author OS Group
 * @version 1.0
 */
public class HeartbeatMonitor {
    
    /** 单例实例 */
    private static HeartbeatMonitor instance;
    
    /** 被监控的项目列表 - 线程安全 */
    private final List<BaseProject> monitoredProjects;
    
    /** 定时任务执行器 */
    private final ScheduledExecutorService scheduler;
    
    /** 监控间隔时间(秒) */
    private final long monitorInterval;
    
    /** 是否正在运行 */
    private volatile boolean isRunning;
    
    /** 异常项目监听器 */
    private HeartbeatListener listener;
    
    /**
     * 私有构造函数（单例模式）
     * 
     * @param monitorInterval 监控间隔时间(秒)
     */
    private HeartbeatMonitor(long monitorInterval) {
        this.monitoredProjects = new CopyOnWriteArrayList<>();
        this.scheduler = Executors.newScheduledThreadPool(1);
        this.monitorInterval = monitorInterval;
        this.isRunning = false;
    }
    
    /**
     * 获取监控器实例（单例）
     * 
     * @param monitorInterval 监控间隔时间(秒)
     * @return 监控器实例
     */
    public static synchronized HeartbeatMonitor getInstance(long monitorInterval) {
        if (instance == null) {
            instance = new HeartbeatMonitor(monitorInterval);
        }
        return instance;
    }
    
    /**
     * 获取监控器实例（默认5秒间隔）
     * 
     * @return 监控器实例
     */
    public static HeartbeatMonitor getInstance() {
        return getInstance(5);
    }
    
    /**
     * 注册项目进行监控
     * 
     * @param project 要监控的项目
     */
    public void registerProject(BaseProject project) {
        if (project != null && !monitoredProjects.contains(project)) {
            monitoredProjects.add(project);
            System.out.println("📝 [心跳监控] 注册项目: " + project.getProjectName());
        }
    }
    
    /**
     * 取消项目监控
     * 
     * @param project 要取消监控的项目
     */
    public void unregisterProject(BaseProject project) {
        if (monitoredProjects.remove(project)) {
            System.out.println("📝 [心跳监控] 取消监控: " + project.getProjectName());
        }
    }
    
    /**
     * 设置心跳监听器
     * 
     * @param listener 监听器
     */
    public void setListener(HeartbeatListener listener) {
        this.listener = listener;
    }
    
    /**
     * 启动监控守护进程
     */
    public void startMonitoring() {
        if (isRunning) {
            System.out.println("⚠️  [心跳监控] 监控已在运行中");
            return;
        }
        
        isRunning = true;
        System.out.println("🚀 [心跳监控] 启动守护进程，监控间隔: " + monitorInterval + " 秒");
        System.out.println("📊 [心跳监控] 监控项目数量: " + monitoredProjects.size());
        
        // 定期执行监控任务
        scheduler.scheduleAtFixedRate(
            this::checkAllProjects,
            monitorInterval,
            monitorInterval,
            TimeUnit.SECONDS
        );
    }
    
    /**
     * 停止监控守护进程
     */
    public void stopMonitoring() {
        if (!isRunning) {
            return;
        }
        
        isRunning = false;
        scheduler.shutdown();
        
        try {
            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
            System.out.println("🛑 [心跳监控] 守护进程已停止");
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 检查所有项目的心跳状态
     */
    private void checkAllProjects() {
        if (monitoredProjects.isEmpty()) {
            return;
        }
        
        System.out.println("\n🔍 [心跳检查] 开始检查 " + monitoredProjects.size() + " 个项目...");
        
        List<BaseProject> deadProjects = new ArrayList<>();
        List<BaseProject> aliveProjects = new ArrayList<>();
        
        for (BaseProject project : monitoredProjects) {
            if (project.isAlive()) {
                aliveProjects.add(project);
            } else {
                deadProjects.add(project);
                handleDeadProject(project);
            }
        }
        
        // 输出检查结果
        System.out.println("✅ 正常项目: " + aliveProjects.size() + " 个");
        if (!deadProjects.isEmpty()) {
            System.out.println("❌ 异常项目: " + deadProjects.size() + " 个");
            for (BaseProject project : deadProjects) {
                System.out.println("   ⚠️  " + project.getProjectName() + 
                                   " - 心跳超时 " + project.getTimeSinceLastHeartbeat() / 1000.0 + " 秒");
            }
        }
        System.out.println();
    }
    
    /**
     * 处理心跳超时的项目
     * 
     * @param project 心跳超时的项目
     */
    private void handleDeadProject(BaseProject project) {
        System.out.println("🚨 [告警] 项目 " + project.getProjectName() + " 心跳超时！");
        
        // 标记项目为异常
        project.setOk(false);
        
        // 触发监听器
        if (listener != null) {
            listener.onHeartbeatTimeout(project);
        }
    }
    
    /**
     * 获取监控报告
     * 
     * @return 监控报告字符串
     */
    public String getMonitorReport() {
        StringBuilder sb = new StringBuilder();
        sb.append("\n╔════════════════════════════════════════════════╗\n");
        sb.append("║         心跳监控系统 - 状态报告                ║\n");
        sb.append("╠════════════════════════════════════════════════╣\n");
        sb.append(String.format("║  监控状态: %s\n", isRunning ? "✅ 运行中" : "🔒 已停止"));
        sb.append(String.format("║  监控间隔: %d 秒\n", monitorInterval));
        sb.append(String.format("║  监控项目数: %d 个\n", monitoredProjects.size()));
        sb.append("╠════════════════════════════════════════════════╣\n");
        
        if (monitoredProjects.isEmpty()) {
            sb.append("║  (无监控项目)\n");
        } else {
            int aliveCount = 0;
            int deadCount = 0;
            
            for (BaseProject project : monitoredProjects) {
                if (project.isAlive()) {
                    aliveCount++;
                } else {
                    deadCount++;
                }
            }
            
            sb.append(String.format("║  正常项目: %d 个\n", aliveCount));
            sb.append(String.format("║  异常项目: %d 个\n", deadCount));
            sb.append("╠════════════════════════════════════════════════╣\n");
            
            // 详细列出每个项目的状态
            for (BaseProject project : monitoredProjects) {
                String status = project.isAlive() ? "✅" : "❌";
                double timeSince = project.getTimeSinceLastHeartbeat() / 1000.0;
                sb.append(String.format("║  %s %s (%.1fs)\n", status, project.getProjectName(), timeSince));
            }
        }
        
        sb.append("╚════════════════════════════════════════════════╝\n");
        
        return sb.toString();
    }
    
    /**
     * 获取所有监控的项目
     * 
     * @return 项目列表
     */
    public List<BaseProject> getMonitoredProjects() {
        return new ArrayList<>(monitoredProjects);
    }
    
    /**
     * 获取异常项目列表
     * 
     * @return 异常项目列表
     */
    public List<BaseProject> getDeadProjects() {
        List<BaseProject> deadProjects = new ArrayList<>();
        for (BaseProject project : monitoredProjects) {
            if (!project.isAlive()) {
                deadProjects.add(project);
            }
        }
        return deadProjects;
    }
    
    /**
     * 检查监控器是否正在运行
     * 
     * @return true表示正在运行
     */
    public boolean isRunning() {
        return isRunning;
    }
    
    /**
     * 心跳监听器接口
     */
    public interface HeartbeatListener {
        /**
         * 当项目心跳超时时调用
         * 
         * @param project 心跳超时的项目
         */
        void onHeartbeatTimeout(BaseProject project);
    }
}
